#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gdbm.h>

void *open_file(char *name, int block_size, int read_write, int mode) {
  return (void *)gdbm_open(name, block_size, read_write, mode, 0);
}

void close_file(void *file) {
  gdbm_close((GDBM_FILE)file);
}

void reorganize(void *file) {
  gdbm_reorganize((GDBM_FILE)file);
}

void sync(void *file) {
  gdbm_sync((GDBM_FILE)file);
}

/* Initialize a datum with a string and return the datum */
datum init_datum(char *str) {
  datum d;

  d.dptr = str;
  d.dsize = strlen(str) + 1;

  return d;
}

int store(void *file, char *key, char *data, int flag) {
  datum key_struct = init_datum(key);
  datum data_struct = init_datum(data);

  /* Store the datum and return the status */
  return gdbm_store((GDBM_FILE)file, key_struct, data_struct, flag);
}

char *fetch(void *file, char *key) {
  datum key_struct = init_datum(key);
  datum data_struct = gdbm_fetch((GDBM_FILE)file, key_struct);
  
  /* Someone will need to call free() on this later */
  return data_struct.dptr;
}

/* Thin wrapper around gdbm_exists() */
int existsp(void *file, char *key) {
  datum key_struct = init_datum(key);
  return gdbm_exists((GDBM_FILE)file, key_struct);
}

/* Thin wrapper around gdbm_delete() */
int delete(void *file, char *key) {
  datum key_struct = init_datum(key);
  return gdbm_delete((GDBM_FILE)file, key_struct);
}

char *firstkey(void *file) {
  datum data_struct = gdbm_firstkey((GDBM_FILE)file);
  
  /* Someone will need to call free() on this later */
  return data_struct.dptr;
}

char *nextkey(void *file, char *key) {
  datum key_struct = init_datum(key);
  datum data_struct = gdbm_nextkey((GDBM_FILE)file, key_struct);
  
  /* Someone will need to call free() on this later */
  return data_struct.dptr;
}

int set_cachesize(void *file, int size) {
  return gdbm_setopt((GDBM_FILE)file, GDBM_CACHESIZE, &size, sizeof(int));
}

int set_syncmode(void *file, int state) {
  return gdbm_setopt((GDBM_FILE)file, GDBM_SYNCMODE, &state, sizeof(int));
}
